package org.gd.hellojavacore.patterns.builder;

import org.gd.hellojavacore.patterns.CreationalPattern;

/**
 <pre>
 Цель

 Отделяет конструирование сложного объекта от его представления, так что в результате одного
 и того же процесса конструирования могут получаться разные представления

 ----------------------------------------------------------------------------------------------

 Плюсы

 позволяет изменять внутреннее представление продукта;
 изолирует код, реализующий конструирование и представление;
 дает более тонкий контроль над процессом конструирования

 ----------------------------------------------------------------------------------------------

 Применение

 алгоритм создания сложного объекта не должен зависеть от того, из каких частей состоит объект
 и как они стыкуются между собой; процесс конструирования должен обеспечивать различные представления
 конструируемого объекта

 ----------------------------------------------------------------------------------------------

 Применение

 Объекты «моникер» в COM есть Строители, инициализируемые строкой. Более того, для их создания
 используется другой Строитель — MkParseDisplayNameEx, который определяет по строке класс моникера,
 создает моникер и инициализирует его этой же строкой.

 Один из этих объектов, URL Moniker, используется для всей загрузки страниц, вложений и документов
 в Microsoft Internet Explorer

 </pre>
 */
public class Builder implements CreationalPattern {

    public static void main(String[] args) {
        Waiter waiter = new Waiter();
        PizzaBuilder hawaiianPizzaBuilder = new HawaiianPizzaBuilder();
        waiter.setPizzaBuilder(hawaiianPizzaBuilder);
        waiter.constructPizza();

        Pizza pizza = waiter.getPizza();
    }
}

/** "Product" */
class Pizza {
    private String dough = "";
    private String sauce = "";
    private String topping = "";

    public void setDough(String dough)     { this.dough = dough; }
    public void setSauce(String sauce)     { this.sauce = sauce; }
    public void setTopping(String topping) { this.topping = topping; }

    public String getDough()   { return dough; }
    public String getSauce()   { return sauce; }
    public String getTopping() { return topping; }
}


/** "Abstract Builder" */
abstract class PizzaBuilder {
    protected Pizza pizza;

    public Pizza getPizza() { return pizza; }
    public void createNewPizzaProduct() { pizza = new Pizza(); }

    public abstract void buildDough();
    public abstract void buildSauce();
    public abstract void buildTopping();
}

/** "ConcreteBuilder" */
class HawaiianPizzaBuilder extends PizzaBuilder {
    public void buildDough()   { pizza.setDough("cross"); }
    public void buildSauce()   { pizza.setSauce("mild"); }
    public void buildTopping() { pizza.setTopping("ham+pineapple"); }
}

/** "ConcreteBuilder" */
class SpicyPizzaBuilder extends PizzaBuilder {
    public void buildDough()   { pizza.setDough("pan baked"); }
    public void buildSauce()   { pizza.setSauce("hot"); }
    public void buildTopping() { pizza.setTopping("pepperoni+salami"); }
}


/** "Director" */
class Waiter {
    private PizzaBuilder pizzaBuilder;

    public void setPizzaBuilder(PizzaBuilder pb) { pizzaBuilder = pb; }
    public Pizza getPizza() { return pizzaBuilder.getPizza(); }

    public void constructPizza() {
        pizzaBuilder.createNewPizzaProduct();
        pizzaBuilder.buildDough();
        pizzaBuilder.buildSauce();
        pizzaBuilder.buildTopping();
    }
}
